package annotool;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

import annotool.io.*;
import annotool.extract.*;
import annotool.select.*;
import annotool.classify.*;
import annotool.clustering.CodeBook;
import annotool.clustering.Histogram;
import ij.ImagePlus;
import ij.gui.NewImage;
import ij.process.*;


/********************************************************************************************

  Image Annotation Tool

  Jie Zhou  July 2008

  Usage:java -Djava.library.path="../mRMRFeatureselector" annotool.Annotator

  Optional Properties (if defaults need to be changed):

  Application Parameters:
    1. data directory and image file extensions.
    2. target file name for annotations.
  Algorithm Parameters:
    1. Number of features to be selected;
    2. "MIQ" vs "MID" (the latter to be added)
    3. SVM parameter
    4. K for K-fold cross validation.
  Todo:
    -- read from a property file: System.getProperty("imagedir")
    -- provide ranked output of the annotation result
  Issues:
    --  SVM's not good for biased distribution? Write a LDA classifier.
    --  If the tool allows num of class > 10, then it should either input as parameter or get from target reader (needed by SVM)
    --  probability estimation is not right. 

     08/11/08
       //Should the images be resized to smaller ones? Currently dimension is 500K. 35->30
       //Should the features be discretized first before sending to mRMR?  0%??! Double check implementation!!!
       //Should the selected  features be shuffled first before sending to classifier???!!!  5 to 45 random.

        k150
       --> 85% by level-1 Haar 3 or 8 features.   
    08/18/08
       // 70% of the set kr45
       // what if don't do feature extraction/selection? What is the base line performance?
          55% for k150 and kr45
          Type 1  fine.  Type 4 are all thought as 1, Some 3 are thought as 1, Some type 2 are thought as 3.
       // what if don't do feature extraction?    0% !
       // Discard the boundary if not power of 2, instead of leaving the original pixel there.

    08/30/08: 100% if don't do feature selection!

    REDESIGN GUI:  09/20/08
    	Help -- Help Contents
        About IANO (image annotation tool)            
 ************************************************************************************************************/

public class Annotator implements Runnable
{
	//These properties will be saved in "./.annotool_properties" for user modification
	//They can also be changed at command line, by simply adding the property name/value pair:
	//    java -Dimgext=.png  classname

	//default system properties
	public final static String DEFAULT_DIR = "k150/"; //"stage4_6/" for embryos
	public final static String DEFAULT_EXT = ".jpg";  //".png"; 
	public final static String DEFAULT_TARGET = "k150_4c_target.txt";  //"target4_6_1.txt";
	public final static String DEFAULT_TESTDIR = "k150/"; //"stage4_6/" for embryos
	public final static String DEFAULT_TESTEXT = ".jpg";  //".png"; 
	public final static String DEFAULT_TESTTARGET = "k150_4c_target.txt";  //"target4_6_1.txt";
	public final static String DEFAULT_EXTRACTOR = "SIFT"; //"None"
	public final static String DEFAULT_SELECTOR = "None";  //"None" //change from "MRMR" on 081007, PHC
	public final static String DEFAULT_CLASSIFIER = "SVM";  

	//default algo properties
	public final static String  DEFAULT_FEATURENUM = "8";
	public final static String  DEFAULT_MRMRTYPE = "mRMR-MIQ"; //081007: revised from "MIQ"
	public final static String  DEFAULT_CHANNEL = "g";
	public final static String  DEFAULT_DEBUG = "false";  //controls feature img display
	public final static String  DEFAULT_FILE = "false";  //file output
	public final static String  DEFAULT_DISCRETE = "false";
	public final static String  DEFAULT_SHUFFLE = "false";
	public final static String  DEFAULT_SVM = "-t 0"; //"-t 2 -c 100 -b 1";
	public final static String  DEFAULT_WAVLEVEL = "1";
	public final static String  DEFAULT_FOLD = "LOO"; 
	public final static String  DEFAULT_OUTPUT = "CV"; 
	public final static String[] OUTPUT_CHOICES = {"TT", "CV"}; //"CLASSIFICATION", "ANNOTATION"};

	//steps
	public final static String DEFAULT_steps = "5";
	// initial sigma
	public final static String DEFAULT_isigma = "1.6f";
	// feature descriptor size
	public final static String DEFAULT_fdsize = "4";
	// feature descriptor orientation bins
	public final static String DEFAULT_fdbins = "8";
	// size restrictions for scale octaves, use octaves < max_size and > min_size only
	public final static String DEFAULT_misize = "32";
	public final static String DEFAULT_masize = "1024";

	public final static String DEFAULT_upscale = "false";
	public final static String DEFAULT_scale = "1.0f";
	public int SIFTFeatureSize;
	public final static String lowNumFeatures = "10";
	public final static String highNumFeatures = "40";
	public final static String selectNumFeatures = "40";
	public final static String  DEFAULT_REPRESENTATION = "HIST";	//CODE OR HIST
	public final static String[] REPRESENTATION_CHOICES = {"CODE", "HIST"}; //;
	public final static String HOUGH_THRESHOLD = "1";
	public final static String LOCATION_BINS = "16";
	public final static String ORIENTATION_BIN = "3";
	public final static String SCALE_BIN = "2";
	public final static String ROD = "0.94f";
	public final static String M_SCORE_THRESHOLD = "0.60f";
	public final static String outputFile = "output.txt";
	public final static String saveImg = "true";
	public final static String saveOutputFile = "true";
	public final static String saveImgDir = "./output_images/";

	//
	public static float mScoreTh, rodTh, initial_sigma, scale;
	public static int houghTh, sCodebookSize, eCodebookSize, fd_size, fd_bins, min_size, max_size, steps,
	houghScale, houghOrie, houghLoc;
	public static boolean upscale;
	//properties values read from environment
	//Hough
	public static String hough_Th = System.getProperty("houghTh", HOUGH_THRESHOLD);
	public static String hough_Loc = System.getProperty("houghLoc", LOCATION_BINS);
	public static String hough_Orie = System.getProperty("houghOrie", ORIENTATION_BIN);
	public static String hough_Scale = System.getProperty("houghScale", SCALE_BIN);
	//
	public static String mScore_Th = System.getProperty("mScoreTh", M_SCORE_THRESHOLD);
	public static String rod_Th = System.getProperty("rod", ROD);
	public static String sCodebook_Size = System.getProperty("startCodebookSize", lowNumFeatures);
	public static String eCodebook_Size = System.getProperty("endCodebookSize", highNumFeatures);
	public static String outputTextFile = System.getProperty("outputFile", outputFile);
	public static String saveOutput= System.getProperty("saveOutput", saveOutputFile);
	public static String saveImage = System.getProperty("saveImg", saveImg);
	public static String saveImageDir = System.getProperty("savImgDir", saveImgDir);
	//SIFT
	public static String SIFT_Steps = System.getProperty("siftSteps", DEFAULT_steps);
	public static String SIFT_InitialSigma = System.getProperty("siftIntSigma", DEFAULT_isigma);
	public static String SIFT_FdSize = System.getProperty("siftFdSize", DEFAULT_fdsize);
	public static String SIFT_FdBins = System.getProperty("siftFdBins", DEFAULT_fdbins);
	public static String SIFT_MinSize = System.getProperty("siftMinSize", DEFAULT_misize);
	public static String SIFT_MaxSize = System.getProperty("siftMaxSize", DEFAULT_masize);
	public static String SIFT_Upscale = System.getProperty("siftUpscale", DEFAULT_upscale);
	public static String SIFT_Scale = System.getProperty("siftScale", DEFAULT_scale);

	public static String dir = System.getProperty("imgdir", DEFAULT_DIR);
	public static String ext = System.getProperty("imgext", DEFAULT_EXT);
	public static String targetFile = System.getProperty("target", DEFAULT_TARGET);

	public static String testdir = System.getProperty("testimgdir", DEFAULT_TESTDIR);
	public static String testext = System.getProperty("testimgext", DEFAULT_TESTEXT); 
	public static String testtargetFile =  System.getProperty("testtarget", DEFAULT_TESTTARGET);

	public static String featureExtractor = System.getProperty("extractor", DEFAULT_EXTRACTOR); 
	public static String featureSelector = System.getProperty("selector", DEFAULT_SELECTOR); 
	public static String classifierChoice = System.getProperty("classifier", DEFAULT_CLASSIFIER); 

	public static String featureNum = System.getProperty("numoffeature", DEFAULT_FEATURENUM);
	public static String channel = System.getProperty("channel", DEFAULT_CHANNEL);
	public static String debugFlag =  System.getProperty("debug", DEFAULT_DEBUG);
	public static String fileFlag = System.getProperty("fileflag", DEFAULT_FILE);
	public static String discreteFlag = System.getProperty("discreteflag",DEFAULT_DISCRETE);
	public static String shuffleFlag = System.getProperty("shuffleflag",DEFAULT_SHUFFLE);
	public static String svmpara = System.getProperty("svmpara",DEFAULT_SVM);
	public static String waveletLevel = System.getProperty("waveletlevel",DEFAULT_WAVLEVEL);
	public static String fold = System.getProperty("fold",DEFAULT_FOLD);
	public static String output = System.getProperty("outputMode", DEFAULT_OUTPUT);

	// Histogram or Codebook
	public static String representation = System.getProperty("representation", DEFAULT_REPRESENTATION);

	//default max num of classes among all columns in the target file. Overwritten later.
	public static int maxClass = 10; 
	java.util.ArrayList<String> annotationLabels = null;
	protected Thread thread; //the running thread for background work.
	protected javax.swing.JProgressBar bar = null;  //if runs in GUI.
	protected javax.swing.JButton goButton = null;  //if runs in GUI.
	protected AnnControlPanel container = null;  //if runs in GUI.
	protected AnnOutputPanel outputPanel = null;  //if runs in GUI.
	protected java.io.Writer outputfile = null;  //will get file name from user;
	protected int[][] trainingTargets, testingTargets; //filled by readxxxTargets();

	public Annotator()
	{}

	public Annotator(javax.swing.JProgressBar bar, javax.swing.JButton goButton, AnnControlPanel container, AnnOutputPanel outputPanel)
	{
		this.bar = bar;
		this.goButton = goButton;
		this.container = container;
		this.outputPanel = outputPanel;
	}

	//This method can be easily replaced by an imagej plugin entrance method.
	public static void main(String[] argv)
	{   
		setProperties();

		if(argv.length >= 1) 
		{
			printUsage(); //print out default parameters in the system.
			return;
		}
		try {
			printUsage();
			(new Annotator()).annotate();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.exit(0);
		}
	}

	public boolean startAnnotation()
	{
		if (thread == null)
			new Thread(this).start();
		else
			return false;

		return true;
	}

	public void run()
	{
		try {
			setProperties();
			annotate();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.exit(0);
		}
	}

	//This function calls one of two modes
	public void annotate() throws IOException
	{
		long total_start_time = System.currentTimeMillis();

		if(saveOutput.equals("true"))
		{
			fileFlag = "true";
			try{
				boolean isCreated = new File(outputTextFile).createNewFile();
				if(isCreated){
					outputfile = new java.io.BufferedWriter(new java.io.FileWriter(outputTextFile));;
					outputfile.write("Start:\n");
					outputfile.flush();
				}
			}catch(Exception e)
			{
				System.out.println("Output File Cann't Be Generated.");
			}

		}
		setProgress(10);

		if (output.equals(OUTPUT_CHOICES[0]))
		{
			System.out.println("Start");
			System.out.println("output:"+ output);
			System.out.println("Mode: Testing Training");
			if(outputfile != null && fileFlag.equals("true"))
				try{
					outputfile.write("Mode: Testing Training"+"\n");
					outputfile.flush();
				}catch(java.io.IOException e)
				{ 
					System.out.println("Writing to output file failed.");
				}
				TTAnnotate();
		}

		else if (output.equals(OUTPUT_CHOICES[1])) 
		{
			System.out.println("Start");
			System.out.println("output:"+ output);
			System.out.println("Mode: Cross Validation");
			if(outputfile != null && fileFlag.equals("true"))
				try{
					outputfile.write("Mode: Cross Validation"+"\n");
					outputfile.flush();
				}catch(java.io.IOException e)
				{ 
					System.out.println("Writing to output file failed.");
				}
				CVAnnotate();
		}
		else
		{
			System.out.println("Output mode:"+output+"is unknown");
			System.exit(0);
		}
		System.out.println( "Done\nTotal Time " + ( System.currentTimeMillis() - total_start_time ) + "ms" );
		if(outputfile != null )
			try{
				outputfile.write("Total Time " + ( System.currentTimeMillis() - total_start_time ) + "ms"+"\n");
				outputfile.flush();
			}catch(java.io.IOException e)
			{ 
				System.out.println("Writing to output file failed.");
			}
			//reset cursur etc after done
			if(outputfile != null && fileFlag.equals("true"))
				try{
					outputfile.close();
				}catch(Exception e) {}

				resetGUI();
	}

	public void TTAnnotate() throws IOException
	{
		//Runtime r = Runtime.getRuntime();
		//long freeMem = r.freeMemory();
		//   System.out.println("free memory before creating array: " + freeMem);
		//read images
		DataInputDynamic trainingProblem = new DataInputDynamic(dir, ext, channel);
		ImagePlus[] dataTrain = trainingProblem.readImagePlus(dir,ext);

		DataInputDynamic testingProblem = new DataInputDynamic(testdir, testext, channel);
		//ImagePlus[] dataTestin = testingProblem.readImagePlus(testdir, testext);


		//read targets
		setProgress(20);
		int numOfAnno = readTrainTestTargets(trainingProblem, testingProblem);
		//r.gc();	//garbage collector
		//freeMem = r.freeMemory();
		//  System.out.println("free memory before creating array: " + freeMem);
		//feature extraction. For 3D, may be it will be combined with getxxData() for memory issue
		setProgress(30);
		float[][] trainingFeatures, testingFeatures;
		float[][] selectedTrainingFeatures = null;
		float[][] codebookTrainingFeatures = null, codebookTestingFeatures = null;
		int trainingLength = trainingProblem.getLength();
		long start_time = System.currentTimeMillis();
		trainingFeatures = getExtractedFeatures(trainingProblem); 
		System.out.println( "Training Features Extract took " + ( System.currentTimeMillis() - start_time ) + "ms" );
		System.out.println("The Default feature size is : "+trainingFeatures[0].length);
		if(outputfile != null )
		try{
			outputfile.write( "Training Features Extract took " + ( System.currentTimeMillis() - start_time ) + "ms."+"\n");
			outputfile.write( "The Default feature size is : "+trainingFeatures[0].length+"\n");
			outputfile.flush();
		}catch(java.io.IOException e)
		{ 
			System.out.println("Writing to output file failed.");
		}
		start_time = System.currentTimeMillis();
		testingFeatures = getExtractedFeatures(testingProblem); 
		System.out.println( "Testing Features Extract took " + ( System.currentTimeMillis() - start_time ) + "ms" );
		if(outputfile != null )
		try{
			outputfile.write( "Training Features Extract took " + ( System.currentTimeMillis() - start_time ) + "ms."+"\n");
			outputfile.flush();
		}catch(java.io.IOException e)
		{ 
			System.out.println("Writing to output file failed.");
		}
		//r.gc();	//garbage collector
		//freeMem = r.freeMemory();
		//System.out.println("free memory before creating array: " + freeMem);

		// --alternate---
		try{
			SiftFeatureSelector SSTrain = new SiftFeatureSelector(trainingFeatures, maxClass, trainingLength, trainingTargets[0], this.SIFTFeatureSize);//081007

			//r.gc();	//garbage collector
			//freeMem = r.freeMemory();
			//  System.out.println("free memory before creating array: " + freeMem);
			start_time = System.currentTimeMillis();
			selectedTrainingFeatures =  SSTrain.select(eCodebookSize, rodTh, mScoreTh);
			System.out.println( "CodeBook Building took " + ( System.currentTimeMillis() - start_time ) + "ms" );
			System.out.println("The selected training "+selectedTrainingFeatures[0].length);
			if(outputfile != null )
			try{
				outputfile.write( "CodeBook Building took " + ( System.currentTimeMillis() - start_time ) + "ms."+"\n");
				outputfile.write( "The selected training "+selectedTrainingFeatures[0].length+"\n");
				outputfile.flush();
			}catch(java.io.IOException e)
			{ 
				System.out.println("Writing to output file failed.");
			}
		}
		catch(Exception e){
			System.out.println("Error: Change the maximum codebook size(eCodebook_Size) to a lesser value.");
			printUsage();
			System.exit(0);
		}
		for ( int i = sCodebookSize; i <= eCodebookSize; i++)
		{
			float[][] codes = new float[selectedTrainingFeatures.length][i * this.SIFTFeatureSize];
			for(int j = 0; j < selectedTrainingFeatures.length; j++)
			{
				for(int k = 0; k < i * this.SIFTFeatureSize; k++)
				{
					codes[j][k] = selectedTrainingFeatures[j][k];
				}
			}
			if (representation.equals(REPRESENTATION_CHOICES[0]))
			{
				start_time = System.currentTimeMillis();
				CodeBook cbTraining = new CodeBook(trainingFeatures, codes, this.SIFTFeatureSize);
				//Histogram cbTraining = new Histogram(trainingFeatures, codes, this.SIFTFeatureSize);
				codebookTrainingFeatures = cbTraining.generator();
				System.out.println( "CodeBook Training Representation took " + ( System.currentTimeMillis() - start_time ) + "ms" );

				start_time = System.currentTimeMillis();
				CodeBook cbTesting = new CodeBook(testingFeatures, codes, this.SIFTFeatureSize);
				//Histogram cbTesting = new Histogram(testingFeatures, codes, this.SIFTFeatureSize);
				codebookTestingFeatures =  cbTesting.generator();
				System.out.println( "CodeBook Testing Representation took " + ( System.currentTimeMillis() - start_time ) + "ms" );
			}
			else if (representation.equals(REPRESENTATION_CHOICES[1]))
			{
				start_time = System.currentTimeMillis();
				Histogram cbTraining = new Histogram(trainingFeatures, codes, this.SIFTFeatureSize);
				codebookTrainingFeatures = cbTraining.generator();
				System.out.println( "CodeBook Training Representation took " + ( System.currentTimeMillis() - start_time ) + "ms" );
				if(outputfile != null )
				try{
					outputfile.write( "CodeBook Training Representation took " + ( System.currentTimeMillis() - start_time ) + "ms."+"\n");
					outputfile.flush();
				}catch(java.io.IOException e)
				{ 
					System.out.println("Writing to output file failed.");
				}
				start_time = System.currentTimeMillis();

				Histogram cbTesting = new Histogram(testingFeatures, codes, this.SIFTFeatureSize);
				codebookTestingFeatures =  cbTesting.generator();
				System.out.println( "CodeBook Testing Representation took " + ( System.currentTimeMillis() - start_time ) + "ms" );
				if(outputfile != null )
				try{
				outputfile.write( "CodeBook Testing Representation took " + ( System.currentTimeMillis() - start_time ) + "ms."+"\n");
					outputfile.flush();
				}catch(java.io.IOException e)
				{ 
					System.out.println("Writing to output file failed.");
				}
				
			}
			else
			{
				System.out.println("Representation mode:"+representation+"is unknown");
				System.exit(0);
			}
			
			// Visualization - 8/8/11
			int[] imgsPerClass = new int[selectedTrainingFeatures.length];
			for(int dat = 0; dat < selectedTrainingFeatures.length; dat++)
			{
				imgsPerClass[dat] = 0;
				for(int imgDat = 0; imgDat < trainingTargets[0].length; imgDat++)
				{
					if((dat+1) == trainingTargets[0][imgDat])
					{
						imgsPerClass[dat]++;
					}
				}

				if(saveImage.equals("true"))
				{
					Visualization visual;

					visual = new Visualization(dataTrain[(dat* imgsPerClass[dat]) ], codes[dat]);
					visual.show();
					BufferedImage buf;
					boolean isCreated = new File(saveImageDir).mkdirs();
					File file;
					buf = visual.showSave(1, Color.blue);

					file = new File(saveImageDir, dataTrain[(dat* imgsPerClass[dat]) ].getTitle());
					try {
						ImageIO.write(buf, "jpg", file);
					} catch (IOException e) {
						// TODO Auto-generated catch block
						//e.printStackTrace();
						System.out.println("Error: Unable to write the image on to the specified path, please check the path and try.");
					}
				}
			}
			// Visualization
			//r.gc();
			//freeMem = r.freeMemory();
			//  System.out.println("free memory before creating array: " + freeMem);
			trainingProblem.setDataNull();
			testingProblem.setDataNull();

			//get number of features
			setProgress(40);
			int numoffeatures = getNumberofFeatures();
			//System.out.println("the number of features are :"+numoffeatures);

			//r.gc();
			//freeMem = r.freeMemory();
			//  System.out.println("free memory before creating array: " + freeMem);
			setProgress(50);
			trainingTestingOutput(trainingProblem, testingProblem, codebookTrainingFeatures, codebookTestingFeatures, trainingTargets, testingTargets, numoffeatures, numOfAnno);
			//r.gc();
			//freeMem = r.freeMemory();
			//  System.out.println("free memory before creating array: " + freeMem);
		}

	} //end of TTAnnotate


	private void trainingTestingOutput(DataInputDynamic trainingProblem, DataInputDynamic testingProblem, float[][] trainingfeatures, float[][] testingfeatures, int[][] trainingtargets, int[][] testingtargets, int numoffeatures, int numOfAnno) throws IOException
	{
		//dimension of extracted features before selection
		int incomingDim = trainingfeatures[0].length;
		int trainingLength = trainingProblem.getLength();
		int testingLength = testingProblem.getLength();

		if (featureSelector.equalsIgnoreCase("None"))
			//use the original feature without selection -- overwrite numoffeatures value
			numoffeatures = incomingDim;
		System.out.println("The number of features are :"+numoffeatures+"\n");

		Classifier classifier = null;

		boolean discrete = Boolean.parseBoolean(discreteFlag);

		Annotation[][] annotations = new Annotation[numOfAnno][testingLength];
		for(int i=0; i < numOfAnno; i++)
			for (int j = 0; j<testingLength; j++)
				annotations[i][j] = new Annotation();

		//pass the training and testing data to Validator
		//get rate and prediction results for testing data
		for (int i = 0; i < numOfAnno; i++)
		{
			float rate = 0;

			if (featureSelector.equalsIgnoreCase("mRMR-MIQ") || featureSelector.equalsIgnoreCase("mRMR-MID"))
			{
				/*//FeatureSelector selector = (new mRMRFeatureSelector(trainingfeatures, trainingtargets[i], trainingLength, width*height, numoffeatures, selectorType, discrete));//081012
				FeatureSelector selector = (new mRMRFeatureSelector(trainingfeatures, trainingtargets[i], trainingLength, incomingDim, numoffeatures, featureSelector, discrete));//081007
				float[][] selectedTrainingFeatures = selector.selectFeatures();
				//selector = (new mRMRFeatureSelector(testingfeatures, testingtargets[i], testingLength, width*height, numoffeatures, selectorType, discrete)); //081012
				selector = (new mRMRFeatureSelector(testingfeatures, testingtargets[i], testingLength, incomingDim, numoffeatures, featureSelector, discrete));//081007
				float[][] selectedTestingFeatures = selector.selectFeatures();

				if (classifierChoice.equalsIgnoreCase("SVM"))
					classifier = new SVMClassifier(numoffeatures, svmpara);
				else if (classifierChoice.equalsIgnoreCase("LDA"))
					classifier = new LDAClassifier(numoffeatures);

				rate = (new Validator()).classify(trainingLength, testingLength,numoffeatures, selectedTrainingFeatures, selectedTestingFeatures, trainingtargets[i], testingtargets[i], classifier, annotations[i]);
				 */}
			else if (featureSelector.equalsIgnoreCase("SIFT") )
			{/*
				//FeatureSelector selector = (new mRMRFeatureSelector(trainingfeatures, trainingtargets[i], trainingLength, width*height, numoffeatures, selectorType, discrete));//081012
				//System.out.println(trainingtargets[i]);
				//FeatureSelector selector = (new mRMRFeatureSelector(features, targets[i], length, width*height, numoffeatures, selectorType, discrete));
				SIFTSelect SSTrain = new SIFTSelect(trainingfeatures, targetFile, trainingProblem.getChildren(), trainingtargets[i], trainingLength, incomingDim, numoffeatures, featureSelector, discrete);//081007
				//SIFT selection
				//float[][] selectedFeatures = selector.selectFeatures();
						//float[][] selectedFeatures = null;
				float[][] selectedTrainingFeatures =  SSTrain.select(trainingProblem.getWidth(),trainingProblem.getHeight());


				SIFTSelect SSTest = new	SIFTSelect(testingfeatures, targetFile, testingProblem.getChildren(), testingtargets[i], testingLength, incomingDim, numoffeatures, featureSelector, discrete);//081007
				//SIFT selection
				//float[][] selectedFeatures = selector.selectFeatures();
						//float[][] selectedFeatures = null;
				float[][] selectedTestingFeatures = SSTest.selecttest(testingProblem.getWidth(),testingProblem.getHeight());
				for(int z = 0; z < trainingLength; z++)
				{
					for(int y =0 ;y<(selectedTrainingFeatures[z].length)/129;y++)
					{
						for(int zm =0 ;zm<129;zm++)
						System.out.println("the features are "+selectedTrainingFeatures[z][(y*129)+zm]);
					}
					System.out.println("\n");
				}

				if (classifierChoice.equalsIgnoreCase("SVM"))
				    classifier = new SVMClassifier(selectedTrainingFeatures[0].length, svmpara);
				else if (classifierChoice.equalsIgnoreCase("LDA"))
				    classifier = new LDAClassifier(selectedTrainingFeatures[0].length);

				rate = (new Validator()).classify(trainingLength, testingLength,numoffeatures, selectedTrainingFeatures, selectedTestingFeatures, trainingtargets[i], testingtargets[i], classifier, annotations[i]);
			 */}
			else  //no feature selection
			{
				long start_time = System.currentTimeMillis();
				if (classifierChoice.equalsIgnoreCase("SVM"))
					classifier = new SVMClassifier(numoffeatures, svmpara);
				else if (classifierChoice.equalsIgnoreCase("LDA"))
					classifier = new LDAClassifier(numoffeatures);
				if(outputfile !=null && fileFlag.equals("true"))
				{
					rate = (new Validator(outputfile)).classify(trainingLength, testingLength, numoffeatures, trainingfeatures,testingfeatures, trainingtargets[i], testingtargets[i], classifier, annotations[i]);
				}
				else
				{
					rate = (new Validator()).classify(trainingLength, testingLength, numoffeatures, trainingfeatures,testingfeatures, trainingtargets[i], testingtargets[i], classifier, annotations[i]);
				}
				System.out.println( "For Classifying " + ( System.currentTimeMillis() - start_time ) + "ms" );
				if(outputfile != null )
				try{
					outputfile.write("For Classifying " + ( System.currentTimeMillis() - start_time ) + "ms."+"\n");
					outputfile.flush();
				}catch(java.io.IOException e)
				{ 
					System.out.println("Writing to output file failed.");
				}
			}
			System.out.println("recognition rate:" + rate);
			if(outputPanel != null)
				outputPanel.setOutput("Recog Rate for "+ annotationLabels.get(i) + ": " + rate);
			if(outputfile != null && fileFlag.equals("true"))
				try{
					outputfile.write("Done."+"\n");
					outputfile.flush();
				}catch(java.io.IOException e)
				{ 
					System.out.println("Writing to output file failed.");
				}
				setProgress(50+(i+1)*50/numOfAnno);
		}

		//put the prediction results back to GUI
		if(container != null)
			container.getTablePanel().updateTestingTable(annotations);
	}

	public void CVAnnotate()
	{
		//------ read image data from the directory ------------//
		//int newd = 64, newh = 64; //DataInput problem = new DataInput(dir, ext, channel, newd, newh);
		DataInputDynamic problem = new DataInputDynamic(dir, ext, channel);
		ImagePlus[] data1 = problem.readImagePlus(dir,ext);


		//----- feature extraction -------//
		setProgress(30);
		long start_time = System.currentTimeMillis();



		float[][] features = getExtractedFeatures(problem); //data,length, width, height);
		System.out.println( " Features Extract took " + ( System.currentTimeMillis() - start_time ) + "ms" );
		if(outputfile != null )
			try{
				outputfile.write(" Features Extract took " + ( System.currentTimeMillis() - start_time ) + "ms" +"\n");
				outputfile.flush();
			}catch(java.io.IOException e)
			{ 
				System.out.println("Writing to output file failed.");
			}
			//Buff image
			/*BufferedImage buf;
		boolean isCreated;
		isCreated = new File("/home/divakaruni/Desktop/images/New_samples_for_HOUGH>2/resul/bmp/SIFT_Hough_Extracted/").mkdirs();
		for(int dat = 0; dat < data1.length; dat++)
		{
		Visualization visual = new Visualization(data1[dat], features[dat]); 
		buf = visual.showSave(2, Color.red);
		File file;

		file = new File("/home/divakaruni/Desktop/images/New_samples_for_HOUGH>2/resul/bmp/SIFT_Hough_Extracted", +dat+".jpg");
		try {
			ImageIO.write(buf, "jpg", file);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		}*/

			//-----  read targets matrix (for multiple annotations, one per column) --------//
			setProgress(20);
			int numOfAnno = readTargets(problem);
			//for(int i=0; i<numOfAnno; i++)
			//	for(int j=0; j<trainingTargets[i].length; j++)
			//		System.out.print(trainingTargets[i][j]+ " ");

			float[][] selectedTrainingFeatures = null, codebookFeatures = null;
			int length = problem.getLength();
			start_time = System.currentTimeMillis();


			try{
				SiftFeatureSelector SSTrain = new SiftFeatureSelector(features, maxClass, length, trainingTargets[0], this.SIFTFeatureSize);//081007
				selectedTrainingFeatures =  SSTrain.select(eCodebookSize, rodTh, mScoreTh);
			}
			catch(Exception e){
				System.out.println("Error: Change the maximum codebook size(eCodebook_Size) to a lesser value.");
				printUsage();
				System.exit(0);
			}

			System.out.println( " CodeBook Building took " + ( System.currentTimeMillis() - start_time ) + "ms" );
			if(outputfile != null )
				try{
					outputfile.write(" CodeBook Building took " + ( System.currentTimeMillis() - start_time ) + "ms" +"\n");
					outputfile.flush();
				}catch(java.io.IOException e)
				{ 
					System.out.println("Writing to output file failed.");
				}
				for ( int i = sCodebookSize; i <= eCodebookSize; i++)
				{
					float[][] codes = new float[selectedTrainingFeatures.length][i * this.SIFTFeatureSize];
					for(int j = 0; j < selectedTrainingFeatures.length; j++)
					{
						for(int k = 0; k < i * this.SIFTFeatureSize; k++)
						{
							codes[j][k] = selectedTrainingFeatures[j][k];
						}
					}
					System.out.println("the selected training "+codes[0].length);
					if(outputfile != null )
						try{
							outputfile.write("\n");
							outputfile.flush();
						}catch(java.io.IOException e)
						{ 
							System.out.println("Writing to output file failed.");
						}
						//	CodeBook cbTraining = new CodeBook(features, codes, this.SIFTFeatureSize);
						//	codebookFeatures = cbTraining.generator();
						if (representation.equals(REPRESENTATION_CHOICES[0]))
						{
							CodeBook cbTraining = new CodeBook(features, codes, this.SIFTFeatureSize);
							codebookFeatures = cbTraining.generator();
						}
						else if (representation.equals(REPRESENTATION_CHOICES[1]))
						{
							Histogram cbTraining = new Histogram(features, codes, this.SIFTFeatureSize);
							codebookFeatures = cbTraining.generator();
						}
						else
						{
							System.out.println("Representation mode:"+representation+"is unknown");
							System.exit(0);
						}

						// Visualization - 8/8/11
						int[] imgsPerClass = new int[selectedTrainingFeatures.length];
						for(int dat = 0; dat < selectedTrainingFeatures.length; dat++)
						{
							imgsPerClass[dat] = 0;
							for(int imgDat = 0; imgDat < trainingTargets[0].length; imgDat++)
							{
								if((dat+1) == trainingTargets[0][imgDat])
								{
									imgsPerClass[dat]++;
								}
							}

							if(saveImage.equals("true"))
							{
								Visualization visual;

								visual = new Visualization(data1[(dat* imgsPerClass[dat]) ], codes[dat]);
								visual.show();
								BufferedImage buf;
								boolean isCreated = new File(saveImageDir).mkdirs();
								File file;
								buf = visual.showSave(1, Color.blue);

								file = new File(saveImageDir, data1[(dat* imgsPerClass[dat]) ].getTitle());
								try {
									ImageIO.write(buf, "jpg", file);
								} catch (IOException e) {
									// TODO Auto-generated catch block
									//e.printStackTrace();
									System.out.println("Error: Unable to write the image on to the specified path, please check the path and try.");
								}
							}
						}
						//Buff image
						//BufferedImage buf;
						/*isCreated = new File("/home/divakaruni/Desktop/images/New_samples_for_HOUGH>2/resul/bmp/codebook/"+"for_"+i+"_features").mkdirs();
			File file;
			System.out.println(codes.length+" ----"+selectedTrainingFeatures.length);
			//for(int dat = 0; dat < selectedTrainingFeatures.length; dat++)
			//{
			//	int partition;
			//	if(dat == 0)
			//	{
			//		partition = 4;
			//	}
			//	else
			//	{
		//			partition = 4;
		//		}
				for(int files = 0; files < data1.length; files++)
				{
					int fileNum = 0;
					if(trainingTargets[0][files] == 3)
						fileNum = 0;
					else if(trainingTargets[0][files] == 4)
						fileNum = 1;
					else if(trainingTargets[0][files] == 1)
					fileNum = 1;
					else if(trainingTargets[0][files] == 0)
						fileNum = 0;
					else if(trainingTargets[0][files] == 2)
						fileNum = 3;
					System.out.println(files+"-"+(trainingTargets[0][files])+"-"+data1[files].getTitle()+"-"+fileNum);
					Visualization visual = new Visualization(data1[files], codes[fileNum]); 
					buf = visual.showSave(3, Color.red);

					file = new File("/home/divakaruni/Desktop/images/New_samples_for_HOUGH>2/resul/bmp/codebook/"+"for_"+i+"_features", +files+".jpg");
					try {
						ImageIO.write(buf, "jpg", file);
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}

						 *///}
						//raw data is not used after this point, set to null, otherwise will be collected after the method exits  
						problem.setDataNull();

						//----- feature selection and annotation for each target column ---------//
						setProgress(40);
						//int numoffeatures =getNumberofFeatures();
						int numoffeatures = 40;


						//System.out.println("the number of features are :"+numoffeatures);

						//-----  output the annotation/classification results
						setProgress(50);
						cvOutput(codebookFeatures, trainingTargets, problem, numoffeatures, numOfAnno);
				}

	}//end of CV annotate


	/*
	 * Output the recognition rate of each task (per column)
	 * This method can use k-fold CV.
	 */
	private void cvOutput(float[][] features, int[][] targets, DataInputDynamic problem, int numoffeatures, int numOfAnno)
	{
		//dimension of extracted features before selection
		int incomingDim = features[0].length;
		System.out.println("the dimension is "+features[0].length);
		int length = problem.getLength();

		/*		if(fileFlag.equals("true"))
			try{
				outputfile = new java.io.BufferedWriter(new java.io.FileWriter(outputTextFile));;
				outputfile.write("Outputs:\n");
				outputfile.flush();
			}catch(Exception e)
			{
				System.out.println("Output File Cann't Be Generated.");
			}
		 */
		if (featureSelector.equalsIgnoreCase("None"))
			//use the original feature without selection -- overwrite numoffeatures value
			numoffeatures = incomingDim;

		Classifier classifier = null;
		if (classifierChoice.equalsIgnoreCase("SVM"))
			classifier = new SVMClassifier(numoffeatures, svmpara);
		else if (classifierChoice.equalsIgnoreCase("LDA"))
			classifier = new LDAClassifier(numoffeatures);

		boolean discrete = Boolean.parseBoolean(discreteFlag);
		boolean shuffle = Boolean.parseBoolean(shuffleFlag);
		int K = 0;
		try
		{
			if (fold.equals("LOO"))
				K = length;
			else K = Integer.parseInt(fold);
		}catch(NumberFormatException e)
		{
			System.out.println("Number of fold is not a valid int. Set to " + length +".");
		}
		if (K <= 0 || K > length)
		{
			System.out.println("Number of fold is not a valid int. Set to " + length +".");
		}

		//allocate space for the results.
		Annotation[][] results = new Annotation[numOfAnno][length];
		for(int i=0; i < numOfAnno; i++)
			for (int j = 0; j<length; j++)
				results[i][j] = new Annotation();

		for (int i =  0; i < numOfAnno; i++)
		{
			float recograte = 0;
			int start = 50+i*50/numOfAnno;
			int region = 50/numOfAnno;

			//put in a method later float[][] getSelectedFeatures(features, targets, ..)
			//combine with ttoutput() for more selector types.
			if (featureSelector.equalsIgnoreCase("mRMR-MIQ") || featureSelector.equalsIgnoreCase("mRMR-MID"))
			{
				System.out.println(targets[i]);
				//FeatureSelector selector = (new mRMRFeatureSelector(features, targets[i], length, width*height, numoffeatures, selectorType, discrete));
				FeatureSelector selector = (new mRMRFeatureSelector(features, targets[i], length, incomingDim, numoffeatures, featureSelector, discrete));//081007
				//SIFT selection
				float[][] selectedFeatures = selector.selectFeatures();
				if(debugFlag.equals("true"))
				{
					for(int j=0; j<length; j++)
						for(int k=0; k<numoffeatures; k++)
							System.out.println(selectedFeatures[j][k]);
				}
				recograte = (new Validator(bar, start, region)).KFold(K, length, numoffeatures, selectedFeatures, targets[i],  classifier, shuffle, results[i]);
			}
			else if (featureSelector.equalsIgnoreCase("SIFT") )
			{/*
					System.out.println(targets[i]);
					//FeatureSelector selector = (new mRMRFeatureSelector(features, targets[i], length, width*height, numoffeatures, selectorType, discrete));
					SIFTSelect selector = (new	SIFTSelect(features, targetFile, problem.getChildren(), targets[i], length, incomingDim, numoffeatures, featureSelector, discrete));//081007
					//SIFT selection
					//float[][] selectedFeatures = selector.selectFeatures();
							//float[][] selectedFeatures = null;
					float[][] selectedFeatures = selector.select(problem.getWidth(),problem.getHeight());
					/*for(int z = 0; z < length; z++)
					{
						for(int y =0 ;y<(selectedFeatures[z].length)/129;y++)
						{
							for(int zm =0 ;zm<129;zm++)
							System.out.println("the features are "+selectedFeatures[z][(y*129)+zm]);
						}
						System.out.println("\n");
					}*/
				/*if(debugFlag.equals("true"))
					{
						for(int j=0; j<length; j++)
							for(int k=0; k<numoffeatures; k++)
							{
								//System.out.println(selectedFeatures[j][k]);
							}
					}
					recograte = (new Validator(bar, start, region)).KFold(K, length, numoffeatures, selectedFeatures, targets[i],  classifier, shuffle, results[i]);
				 */}
			else //no feature selection
			{

				if(outputfile !=null && fileFlag.equals("true"))
				{
					recograte = (new Validator(outputfile, bar, start ,region)).KFold(K, length, numoffeatures, features, targets[i],  classifier, shuffle, results[i]);

				}
				else
				{
					recograte = (new Validator(bar, start ,region)).KFold(K, length, numoffeatures, features, targets[i],  classifier, shuffle, results[i]);
				}
			}
			//output
			//System.out.println("rate for annotation target "+ i + ": " + recograte);
			if(outputPanel != null)
				outputPanel.setOutput("Recog Rate for "+ annotationLabels.get(i) + ": " + recograte);
			if(outputfile != null && fileFlag.equals("true"))
				try{
					outputfile.write("Done."+"\n");
					outputfile.flush();
				}catch(java.io.IOException e)
				{ 
					System.out.println("Writing to output file failed.");
				}
		}
		/*
			for(int j = 0; j < length; j++)
			{
				System.out.print("\n");
				for (int i = 0; i < numOfAnno; i++)
					System.out.print("real ann:"+targets[i][j] + " predicted ann:" +results[i][j].anno+'\t');
			}
		 */

		//put the prediction results back to GUI
		if(container != null)
			container.getTablePanel().updateCVTable(results);
	}

	/*
	 *Output the annotation detailed results for each image, 
	 *different from classification output, this method always uses LOO
	 *This method is not used and will be combined into cvOutput() 09/2008
	 */
	/*
	private void annotationOutput(String[] children, float[][] features, int[][] targets, int length, int width, int height, int numoffeatures, int numOfAnno)
	{
		if (featureSelector.equalsIgnoreCase("None"))
			//use the orignial feature without selection -- overwrite numoffeatures value
			numoffeatures = width*height;

		SVMClassifier classifier = new SVMClassifier(numoffeatures, svmpara);
		boolean discrete = Boolean.parseBoolean(discreteFlag);
		boolean shuffle = Boolean.parseBoolean(shuffleFlag);

		//allocate space for the results.
		Annotation[][] annotations = new Annotation[numOfAnno][length];
		for(int i=0; i < numOfAnno; i++)
			for (int j = 0; j<length; j++)
				annotations[i][j] = new Annotation();

		for (int i = 0; i < numOfAnno; i++)
		{
			int start = 50+i*50/numOfAnno;
			int region = 50/numOfAnno;

			if (featureSelector.equalsIgnoreCase("MRMR-MIQ") || featureSelector.equalsIgnoreCase("MRMR-MID"))
			{
				//FeatureSelector selector = (new mRMRFeatureSelector(features, targets[i], length, width*height, numoffeatures, selectorType, discrete));
				FeatureSelector selector = (new mRMRFeatureSelector(features, targets[i], length, width*height, numoffeatures, featureSelector, discrete)); //081007, by PHC
				float[][] selectedFeatures = selector.selectFeatures();
				(new Validator(bar, start, region)).LOO(length, numoffeatures, selectedFeatures, targets[i],  classifier, annotations[i], shuffle);
			}
			else
			{
				(new Validator(bar, start, region)).LOO(length, numoffeatures, features, targets[i],  classifier, annotations[i], shuffle);
			}
		}

		//Can be sorted based on probability later.
		for(int j = 0; j < length; j++)
		{
			//System.out.print("\n"+ children[j]+ " ");
			System.out.print("\n");
			for (int i= 0; i < numOfAnno; i++)
				//  if (annotations[i][j].anno == 1)
				//    System.out.print("anno "+ i +": "+ annotations[i][j].anno + "("+ annotations[i][j].prob +")\t");
				System.out.print("t:"+targets[i][j] + " p:" +annotations[i][j].anno+'\t');
		}
	}*/


	private void drawFeatures(float[][] features, int width, int height, int length)
	{

		//for(int i = 0; i < length; i++)
		for(int i = 0; i < 1; i++)
		{
			byte[] pixels =  new byte[width*height];
			//find out min/max of features
			float min=0,max=0;
			for(int j=0; j < width*height; j++)
				if (min > features[i][j])
					min = features[i][j];
				else if (max < features[i][j])
					max = features[i][j];

			//set value
			for(int j=0; j < width*height; j++)
				//resize to 0-255
				pixels[j] = (byte) ((features[i][j] - min)/(max-min) * 255);

			//set up image
			ImagePlus testimg = NewImage.createByteImage("feature image"+ i,  width, height, 1, NewImage.FILL_BLACK);
			ImageProcessor test_ip = testimg.getProcessor();
			test_ip.setPixels(pixels);
			testimg.show();
			testimg.updateAndDraw();
		}
		//debug
		/*
   		   if(debugFlag.equals("true"))
		   {
    		  System.out.println("feature:");
              for(int i = 0; i < length; i++)
     	        for (int j = 0; j< width*height; j++)
     	          System.out.print(features[i][j]+" ");
	       }*/
	}

	private static void setProperties()
	{
		//
		try{
			mScoreTh = Float.parseFloat(mScore_Th);
			rodTh = Float.parseFloat(rod_Th);
			houghTh = Integer.parseInt(hough_Th);
			houghScale = Integer.parseInt(hough_Scale);
			houghOrie = Integer.parseInt(hough_Orie);
			houghLoc = Integer.parseInt(hough_Loc);
			sCodebookSize = Integer.parseInt(sCodebook_Size);
			eCodebookSize = Integer.parseInt(eCodebook_Size);
			initial_sigma = Float.parseFloat(SIFT_InitialSigma);
			steps = Integer.parseInt(SIFT_Steps);
			scale = Float.parseFloat(SIFT_Scale);
			fd_size = Integer.parseInt(SIFT_FdSize);
			fd_bins = Integer.parseInt(SIFT_FdBins);
			min_size = Integer.parseInt(SIFT_MinSize);
			max_size = Integer.parseInt(SIFT_MaxSize);
			upscale = Boolean.parseBoolean(SIFT_Upscale);
			if(outputTextFile == null || saveOutput == null || saveImage == null || saveImageDir == null || dir == null || ext == null || targetFile == null || 
					testdir == null || testext == null || testtargetFile == null || svmpara == null || fold == null || output == null ||
					outputTextFile.equals("") || saveOutput.equals("") || saveImage.equals("") || saveImageDir.equals("") || dir.equals("") || ext.equals("") || targetFile.equals("") || 
					testdir.equals("") || testext.equals("") || testtargetFile.equals("") || svmpara.equals("") || fold.equals("") || output.equals(""))
			{
				System.out.println("Error: Please check the input parameters and usage.");
				printUsage();
				System.exit(0);
			}
		}
		catch(Exception e){
			//e.printStackTrace();
			System.out.println("Error: Please check the input parameters and usage.");
			printUsage();
			System.exit(0);
		}
		//
	}
	private static void printUsage()
	{
		System.out.println("Usage: java [jvmparameters] [properties] annotool.Annotator");
		System.out.println("Example: java -Xms500M -Xmx -Dimgdir=k150/ annotool.Annotator");
		System.out.println("You will need to place imageJ, Jama, libSVM jar files in the lib folder.");
		//System.out.println("You may also need to set java.library.path to include the native mRMR library.");

		System.out.println("\nDefault parameters: ");
		System.out.println("\timgdir:"+DEFAULT_DIR);
		System.out.println("\timgext:"+DEFAULT_EXT);
		System.out.println("\ttarget:" + DEFAULT_TARGET);
		System.out.println("\ttestimgdir:" + DEFAULT_TESTDIR);
		System.out.println("\ttestext:" + DEFAULT_TESTEXT);
		System.out.println("\ttesttarget:" + DEFAULT_TESTTARGET);
		System.out.println("\tsaveOutput:" + saveOutputFile);
		System.out.println("\toutputFile:" + outputFile);
		System.out.println("\tsaveImg:" + saveImg);
		System.out.println("\tsaveImgDir:" + saveImgDir);
		
		System.out.println("\toutputMode:" + DEFAULT_OUTPUT);

		System.out.println("\tsiftSteps:"+DEFAULT_steps);
		System.out.println("\tsiftIntSigma:"+DEFAULT_isigma);
		System.out.println("\tsiftFdSize:"+DEFAULT_fdsize);
		System.out.println("\tsiftFdBins:"+DEFAULT_fdbins);
		System.out.println("\tsiftMinSize:"+DEFAULT_misize);
		System.out.println("\tsiftMaxSize:"+DEFAULT_masize);
		System.out.println("\tsiftUpscale:"+DEFAULT_upscale);
		System.out.println("\tsiftScale:"+DEFAULT_scale);
		
		System.out.println("\thoughTh:"+HOUGH_THRESHOLD);
		System.out.println("\thoughScale:"+SCALE_BIN);
		System.out.println("\thoughOrie:"+ORIENTATION_BIN);
		System.out.println("\thoughLoc:"+LOCATION_BINS);
		
		System.out.println("\tmScoreTh:"+M_SCORE_THRESHOLD);
		System.out.println("\trod:"+ROD);
		System.out.println("\tstartCodebookSize:" + lowNumFeatures);
		System.out.println("\tendCodebookSize:" + highNumFeatures);
		//System.out.println("\textractor:"+ DEFAULT_EXTRACTOR); 
		//System.out.println("\tselector:"+ DEFAULT_SELECTOR); 

		//System.out.println("\tchannel:"+DEFAULT_CHANNEL + "(for 3 channel color images)");
		//System.out.println("\tnumoffeature:" + DEFAULT_FEATURENUM + "(for feature selector)");
		System.out.println("\tsvmpara:"+DEFAULT_SVM);
		//System.out.println("\twaveletlevel:"+DEFAULT_WAVLEVEL);
		System.out.println("\tfold:"+DEFAULT_FOLD);
		
	}

	private void setProgress(int currentProgress)
	{
		if (bar!=null) bar.setValue(currentProgress);
	}

	private void resetGUI()
	{
		if (bar != null)
		{
			goButton.setEnabled(true);
			container.setCursor(null); //turn off the wait cursor
			bar.setValue(0);
		}
	}

	/*
	 * return: number of annotations. Also pass back targets via parameters
	 */
	private int readTrainTestTargets(DataInputDynamic trainingProblem, DataInputDynamic testingProblem)
	{
		int numOfAnnotations = 0;
		try
		{
			//training
			int trainingLength = trainingProblem.getLength();
			LabelReader labelReader = new LabelReader(trainingLength);
			trainingTargets = labelReader.getTargets(targetFile, trainingProblem.getChildren());
			maxClass = labelReader.getNumOfClasses();
			annotationLabels = labelReader.getAnnotations();
			//testing	
			int testingLength = testingProblem.getLength();
			labelReader = new LabelReader(testingLength);
			testingTargets = labelReader.getTargets(testtargetFile, testingProblem.getChildren());

			numOfAnnotations = labelReader.getNumOfAnnotations();
		}catch(Exception e)
		{ 
			//e.printStackTrace();
			System.out.println("Error: Please format the target file properly.");
			System.exit(0);
		}

		return numOfAnnotations;
	}

	/* 
	 * for CV, only return 1 target matrix, and the number of annotations
	 * 
	 */
	private int readTargets(DataInputDynamic problem)
	{
		int numOfAnno = 0;
		try
		{
			int length = problem.getLength();
			LabelReader labelReader = new LabelReader(length);
			trainingTargets = labelReader.getTargets(targetFile, problem.getChildren());
			maxClass = labelReader.getNumOfClasses();
			annotationLabels = labelReader.getAnnotations();
			numOfAnno = labelReader.getNumOfAnnotations();

			//if(debugFlag.equals("true"))
			//{
			//	for(int i=0; i<numOfAnno; i++)
			//	for(int j=0; j<length; j++)
			//	System.out.print(trainingtargets[i][j]+ " ");
			//}
		}catch(Exception e)
		{   
			//e.printStackTrace();
		System.out.println("Error: Please format the target file properly.");
		System.exit(0);
		}

		return numOfAnno;
	}

	private float[][] getExtractedFeatures(DataInputDynamic problem)
	{
		float[][] features = null;
		//int stackSize = problem.getStackSize(); //for testing sift only
		//ImagePlus[] data1 = problem.readImagePlus(dir,ext);


		if (featureExtractor.equals("HAAR"))
		{/*
			int level;
			try
			{
				level = Integer.parseInt(waveletLevel);
			}catch(NumberFormatException e)
			{
				System.out.println("Number of wavelet levels is not a valid int. Set to " + DEFAULT_WAVLEVEL +".");
				level = Integer.parseInt(DEFAULT_WAVLEVEL);
			}
			if(stackSize == 1)
			  features = (new HaarFeatureExtractor(problem, level)).getFeatures();
			else if (stackSize > 1)//3D image stack
			  features = (new StackSimpleHaarFeatureExtractor(problem, level)).calcFeatures();	
			else
			{
				System.out.println("invalid stack size: " + stackSize);
			}
		 */ // for testing only sift
		}
		else if (featureExtractor.equals("SIFT"))
		{
			//features =(new SIFTExtractor(problem, data1)).run("0");
			//features =(new SIFTExtractor(problem)).run("0");
			try{
				SIFTExtractor SIFT = null;
				if(outputfile !=null && fileFlag.equals("true"))
				{
					SIFT = new SIFTExtractor(outputfile, problem, steps,  scale, initial_sigma, fd_size, fd_bins, min_size, 
							max_size, upscale, houghTh, houghScale, houghOrie, houghLoc);
				}
				else
				{
					SIFT = new SIFTExtractor(problem, steps,  scale, initial_sigma, fd_size, fd_bins, min_size, 
							max_size, upscale, houghTh, houghScale, houghOrie, houghLoc);
				}
				features = SIFT.run("0");
				this.SIFTFeatureSize = SIFT.getFeatureSize();
			}
			catch(Exception e){
				System.out.println("Error: Insufficient features, Please change the SIFT parameters.");
				printUsage();
				System.exit(0);
			}
		}
		/*else // if (featureExtractor.equals("NONE")), use raw image or middle stack for 3D
		{
			int length = problem.getLength(); 
			int height = problem.getHeight();
			int width = problem.getWidth();
			byte[][] data = problem.getData(stackSize/2+1);
			features = new float[length][width*height];
			for(int i = 0; i < length; i++)
				for (int j=0; j < width*height; j++)
					features[i][j] = (float) data[i][j];
		}
		//debug: draw the feature image
		if(debugFlag.equals("true"))
		{
			int length = problem.getLength(); 
			int height[] = problem.getHeightList();
			int width[] = problem.getWidthList();
			drawFeatures(features, width, height, length);
		}*/ // for testing only sift

		return features;
	}


	private int getNumberofFeatures()
	{
		int numoffeatures;

		try
		{
			numoffeatures = Integer.parseInt(featureNum);
		}catch(NumberFormatException e)
		{
			System.out.println("Number of features is not a valid int. Set to " + DEFAULT_FEATURENUM +".");
			numoffeatures = Integer.parseInt(DEFAULT_FEATURENUM);
		}
		return numoffeatures;
	}

}


